/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
"use strict";
import * as htmlparser2 from './htmlParser2.js'

var XMLWriter = /** @class */ (function () {
    function XMLWriter(html, property) {
        this.version = null;
        this.standalone = null;
        this.outputEncoding = '';
        this.htmlMode = false;
        this.unicodeMode = false;
        this.overridePublic = null;
        this.forceDTD = false;
        this.overrideSystem = null;
        this.xmlDeclaration = 'no';
        this.elementLevel = 0;
        this.hasOutputDTD = false;
        this.cdataElement = false;
        this.html = null;
        this.uri = 'http://www.w3.org/1999/xhtml';
        this.booleans = ['checked', 'compact', 'declare', 'defer', 'disabled', 'ismap',
            'multiple', 'nohref', 'noresize', 'noshade', 'nowrap', 'readonly', 'selected'];
        this.tags = ['area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param'];
        this.xmlContent = [];
        this.html = html;
        if (property) {
            for (var i = 0; i < property.length; i++) {
                this.setOutputProperty(property[i].key, property[i].value);
            }
        }
    }
    XMLWriter.prototype.convertToXML = function (callback) {
        this.xmlContent = [];
        var that = this;
        if (!!!this.html) {
            callback(null, new Error('html error'));
            return;
        }
        var parser = new htmlparser2.Parser({
            onparserinit: function (parser) {
                that.xmlContent.push(that.startDocument());
            },
            onprocessinginstruction: function (name, data) {
                if (that.forceDTD) {
                    that.xmlContent.push(that.startDTD(data));
                }
            },
            onopentag: function (name, attribs) {
                that.xmlContent.push(that.startElement(name, attribs));
            },
            ontext: function (data) {
                if (!that.cdataElement) {
                    var chars = data.split('');
                    that.xmlContent.push(that.writeEsc(chars, 0, chars.length, false));
                }
                else {
                    that.xmlContent.push(data);
                }
            },
            onclosetag: function (name) {
                that.xmlContent.push(that.endElement(name));
            },
            onend: function () {
                that.xmlContent.push(that.endDocument());
                callback && callback(that.xmlContent.join(''));
                that.xmlContent = [];
            },
            onerror: function (error) {
                that.xmlContent = [];
                callback && callback(null, error);
            }
        });
        parser.write(this.html);
        parser.end();
    };
    XMLWriter.prototype.setOutputProperty = function (key, value) {
        if (!key || !value) {
            return;
        }
        if (key === XMLWriter.OMIT_XML_DECLARATION) {
            this.xmlDeclaration = value;
        }
        else if (key === XMLWriter.ENCODING) {
            this.outputEncoding = value;
            this.unicodeMode = value.substring(0, 3).toLowerCase() === 'utf';
        }
        else if (key === XMLWriter.METHOD) {
            this.htmlMode = (value === 'html');
        }
        else if (key === XMLWriter.DOCTYPE_PUBLIC) {
            this.overridePublic = value;
            this.forceDTD = true;
        }
        else if (key === XMLWriter.DOCTYPE_SYSTEM) {
            this.overrideSystem = value;
            this.forceDTD = true;
        }
        else if (key === XMLWriter.VERSION) {
            this.version = value;
        }
        else if (key === XMLWriter.STANDALONE) {
            this.standalone = value;
        }
    };
    XMLWriter.prototype.startDocument = function () {
        var start = '';
        if ('yes' != this.xmlDeclaration) {
            start += '<?xml';
            if (this.version == null) {
                start += " version=\"1.0\"";
            }
            else {
                start += " version=\"".concat(this.version, "\"");
            }
            if (this.outputEncoding != null && this.outputEncoding != "") {
                start += " encoding=\"".concat(this.outputEncoding, "\"");
            }
            if (this.standalone == null) {
                start += " standalone=\"yes\"?>\n";
            }
            else {
                start += " standalone=\"".concat(this.standalone, "\"?>\n");
            }
        }
        return start;
    };
    XMLWriter.prototype.endDocument = function () {
        return '\n';
    };
    XMLWriter.prototype.startElement = function (qName, atts) {
        var element = '';
        this.elementLevel++;
        element += "<".concat(qName);
        element += this.writeAttributes(atts);
        element += this.writeNSDecls(qName, atts);
        element += '>';
        if (this.htmlMode && (qName === 'script' || qName === 'style')) {
            this.cdataElement = true;
        }
        return element;
    };
    XMLWriter.prototype.endElement = function (qName) {
        var endContent = '';
        if (!(this.htmlMode && this.tags.indexOf(qName) != -1)) {
            endContent += "</".concat(qName, ">");
        }
        if (this.elementLevel == 1) {
            endContent += '\n';
        }
        this.cdataElement = false;
        this.elementLevel--;
        return endContent;
    };
    XMLWriter.prototype.startDTD = function (data) {
        var dtd = '';
        if (data == null || this.hasOutputDTD) {
            return dtd;
        }
        this.hasOutputDTD = true;
        dtd += "<".concat(data);
        var systemid = '';
        var publicid = '';
        if (this.overrideSystem != null) {
            systemid = this.overrideSystem;
        }
        var sysquote = (systemid.indexOf("\"") != -1) ? "'" : "\"";
        if (this.overridePublic != null) {
            publicid = this.overridePublic;
        }
        if ('' != publicid) {
            var pubquote = (publicid.indexOf("\"") != -1) ? "'" : "\"";
            dtd += " PUBLIC ".concat(pubquote).concat(publicid).concat(pubquote, " ");
        }
        else {
            dtd += ' SYSTEM ';
        }
        dtd += sysquote + systemid + sysquote + '>\n';
        return dtd;
    };
    XMLWriter.prototype.writeAttributes = function (atts) {
        var content = '';
        for (var key in atts) {
            var chars = atts[key].split('');
            content += ' ' + key;
            if (this.htmlMode && this.booleanAttribute(key, atts[key])) {
                break;
            }
            content += "=\"".concat(this.writeEsc(chars, 0, chars.length, true), "\"");
        }
        return content;
    };
    XMLWriter.prototype.writeNSDecls = function (qName, atts) {
        if (qName === 'html') {
            for (var key in atts) {
                if (key.indexOf('xmlns') != -1) {
                    return '';
                }
            }
            return " xmlns=\"".concat(this.uri, "\"");
        }
        return '';
    };
    XMLWriter.prototype.booleanAttribute = function (qName, value) {
        var name = qName;
        var index = qName.indexOf(':');
        if (index != -1) {
            name = qName.substring(index + 1, qName.length);
        }
        if (name != value) {
            return false;
        }
        for (var j = 0; j < this.booleans.length; j++) {
            if (name === this.booleans[j]) {
                return true;
            }
        }
        return false;
    };
    XMLWriter.prototype.writeEsc = function (chars, start, length, isAttVal) {
        var esc = '';
        for (var i = start; i < length; i++) {
            switch (chars[i]) {
                case '&':
                    esc += '&amp;';
                    break;
                case '<':
                    esc += '&lt;';
                    break;
                case '>':
                    esc += '&gt;';
                    break;
                case '"':
                    if (isAttVal) {
                        esc += '&quot;';
                    }
                    else {
                        esc += '"';
                    }
                    break;
                default:
                    if (!this.unicodeMode && chars[i] > '\u00ff') {
                        esc += "&#".concat(chars[i], ";");
                    }
                    else {
                        esc += chars[i];
                    }
                    break;
            }
        }
        return esc;
    };
    XMLWriter.ENCODING = 'encoding';
    XMLWriter.METHOD = 'method';
    XMLWriter.DOCTYPE_PUBLIC = 'doctype-public';
    XMLWriter.DOCTYPE_SYSTEM = 'doctype-system';
    XMLWriter.VERSION = 'version';
    XMLWriter.STANDALONE = 'standalone';
    XMLWriter.OMIT_XML_DECLARATION = 'omit-xml-declaration';
    return XMLWriter;
}());
export {XMLWriter};